//
//  SCoreData.m
//  STool
//
//  Created by banggo on 15/7/13.
//
//

#import "SCoreData.h"
#import <objc/runtime.h>


#define scLOG 1
#if scLOG
#define SCDLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define SCDLog(fmt, ...)
#endif
@implementation SCoreData


@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            SCDLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

#pragma mark - Core Data stack

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:self.databaseName withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }
    
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.sqlite",self.databaseName]];
    
    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        SCDLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    
    return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory

// Returns the URL to the application's Documents directory.获取Documents路径
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

#pragma mark - Others

- (void)dictionaryToEntity:(NSDictionary *)dict entity:(NSObject*)entity
{
    if (dict && entity) {
        for (NSString *keyName in [dict allKeys]) {
            SEL coreDataSetValue = NSSelectorFromString(@"setValue:forKey:");
            if ([entity respondsToSelector:coreDataSetValue]) {
                [entity performSelector:coreDataSetValue withObject:[dict objectForKey:keyName] withObject:keyName];
            }
        }
    }
}

#pragma mark - Core封装

+ (id)sharedInstance
{
    static dispatch_once_t pred;
    static SCoreData *sharedInstance = nil;
    dispatch_once(&pred, ^{
        sharedInstance = [[SCoreData alloc] init];
    });
    return sharedInstance;
}
- (instancetype)setTableName:(NSString *)tableName andDatabaseName:(NSString*)databaseName;
{
    if (!tableName && self.tableName) {
    }
    else
    {
        self.tableName = tableName;
    }
    if (!databaseName && self.databaseName) {
        return self;
    }
    self.databaseName = databaseName;
    return self;
}
/**
 *  插入数据
 *
 *  @param dictionary 需要插入的字典数据
 *  @param key        需要检查的参数(nil即为无检查参数)
 *
 *  @return 是否成功
 */
- (BOOL)insertCoreData:(NSDictionary*)dictionary andKey:(NSString*)key,...NS_REQUIRES_NIL_TERMINATION
{
    if (!self.databaseName || !self.tableName) {
        return NO;
    }
    

    NSMutableArray *getAllKey = [NSMutableArray array];
    if (key) {
        [getAllKey addObject:key];
    }
    va_list arguments;
    va_start(arguments, key);
    NSString *getKey;
    if(key)
    {
        while((getKey = va_arg(arguments,NSString *)))
        {
            if (getKey) {
                [getAllKey addObject:getKey];
            }
        }
    }
    va_end(arguments);
    
   
    
    
    /**
     *  查询数据（如果有相同的数据便不插入）
     */
    if ([getAllKey count]>0) {
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSString *predicateString = [NSString stringWithFormat:@"%@ = '%@'",[getAllKey objectAtIndex:0],[dictionary objectForKey:[getAllKey objectAtIndex:0]]];
        for (int i = 1 ;i<[getAllKey count];i++) {
            predicateString = [NSString stringWithFormat:@"%@ AND %@ = '%@'",predicateString,[getAllKey objectAtIndex:i],[dictionary objectForKey:[getAllKey objectAtIndex:i]]];
        }
        //    predicateString = @"carId = '1441853981'";
        fetchRequest.predicate = [NSPredicate predicateWithFormat:predicateString];
        NSEntityDescription *entity = [NSEntityDescription entityForName:self.tableName inManagedObjectContext:[self managedObjectContext]];
        [fetchRequest setEntity:entity];
        NSError *error;
        NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
        /**
         *  判断key相同
         */
        if ([fetchedObjects count]>0) {
            SCDLog(@"插入失败，拥有相同数据：%@",[error localizedDescription]);
            return NO;
        }
    }
   
    /**
     *  插入数据
     */
    NSManagedObject *inseobject =  [NSEntityDescription insertNewObjectForEntityForName:self.tableName inManagedObjectContext:[self managedObjectContext]];
    [self dictionaryToEntity:dictionary entity:inseobject];
    NSError *error2;
    if(![[self managedObjectContext] save:&error2])
    {
        SCDLog(@"插入失败：%@",[error2 localizedDescription]);
        return NO;
    }
    SCDLog(@"成功插入：%@",[error2 localizedDescription]);
     return YES;
}

/**
 *  便利查询
 *
 *  @param pageSize    查多少条
 *  @param currentPage 从第几条开始查
 *
 *  @return 返回数据
 */
- (NSMutableArray*)selectData:(int)pageSize
                    andOffset:(int)currentPage
             andCompositorKey:(NSString*)compostinStr;
{
    if (!self.databaseName || !self.tableName) {
        return nil;
    }
    
    /**
     拼接条件
     */
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    if (compostinStr) {
        /**
         *  排序
         */
        NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:compostinStr ascending:NO];
        fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    }
//    [fetchRequest setFetchBatchSize:currentPage*pageSize];
    [fetchRequest setFetchLimit:pageSize];
    [fetchRequest setFetchOffset:currentPage];
    
    NSEntityDescription *entity = [NSEntityDescription entityForName:self.tableName inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:entity];
    NSError *error;
    NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count]<1) {
        SCDLog(@"查询失败 error:%@",[error localizedDescription]);
        return nil;
    }
    NSMutableArray *resultArray = [NSMutableArray array];
    
    for (NSManagedObject *getObjects in fetchedObjects) {
        [resultArray addObject:getObjects];
    }
    return resultArray;
}
+(id)getObjectWithClassName:(NSString *)aClassName {
    id rtnObject = nil;
    Class myClazz = NSClassFromString(aClassName);
    if (myClazz) {
        rtnObject = [[myClazz alloc] init];
    }
    return rtnObject;
}

- (NSMutableArray*)selectData:(int)pageSize
                    andOffset:(int)currentPage
             andCompositorKey:(NSString*)compostinStr
               andKeyAndValue:(id)ids,...NS_REQUIRES_NIL_TERMINATION;
{
    if (!self.databaseName || !self.tableName) {
        return nil;
    }
//    NSLog(@"%lu",[self getDataCount]);
    NSMutableArray *getAllObject = [NSMutableArray array];
    va_list arguments;
    va_start(arguments, ids);
    NSString *getKey;
    if(ids)
    {
        while((getKey = va_arg(arguments,NSString *)))
        {
            if (getKey) {
                [getAllObject addObject:getKey];
            }
        }
    }
    va_end(arguments);
    if (ids)
        [getAllObject insertObject:ids atIndex:0];
    
    
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    if ([getAllObject count]%2==0) {
        /**
         *  查询语句
         */
        NSString *predicateString = [NSString stringWithFormat:@"%@ = '%@'",[getAllObject objectAtIndex:0],[getAllObject objectAtIndex:1]];
        for (int i = 2 ;i<[getAllObject count];) {
            predicateString = [NSString stringWithFormat:@"%@ AND %@ = '%@'",predicateString,[getAllObject objectAtIndex:i],[getAllObject objectAtIndex:i+1]];
            i = i+2;
        }
        fetchRequest.predicate = [NSPredicate predicateWithFormat:predicateString];
    }
    [fetchRequest setFetchLimit:pageSize];
    [fetchRequest setFetchOffset:currentPage ];
    if (compostinStr) {
        /**
         *  排序
         */
        NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:compostinStr ascending:NO];
        fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    }
    NSEntityDescription *entity = [NSEntityDescription entityForName:self.tableName inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:entity];
    NSError *error;
    NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count]<1) {
        SCDLog(@"查询失败 error:%@",[error localizedDescription]);
        return [NSMutableArray array];
    }
    NSMutableArray *resultArray = [NSMutableArray array];
    for (NSManagedObject *getObjects in fetchedObjects) {
        [resultArray addObject:getObjects];
    }
    return resultArray;
    
}


//删除
-(BOOL)deleteDataWithKeyAndValue:(id)ids,...NS_REQUIRES_NIL_TERMINATION;
{
    if (!self.databaseName || !self.tableName) {
        return nil;
    }
    
    NSMutableArray *getAllObject = [NSMutableArray array];
    va_list arguments;
    va_start(arguments, ids);
    NSString *getKey;
    if(ids)
    {
        while((getKey = va_arg(arguments,NSString *)))
        {
            if (getKey) {
                [getAllObject addObject:getKey];
            }
        }
    }
    va_end(arguments);
    [getAllObject insertObject:ids atIndex:0];
    
    if ([getAllObject count]<1) {
        return nil;
    }
    NSString *predicateString = [NSString stringWithFormat:@"%@ = '%@'",[getAllObject objectAtIndex:0],[getAllObject objectAtIndex:1]];
    for (int i = 2 ;i<[getAllObject count];) {
        predicateString = [NSString stringWithFormat:@"%@ AND %@ = '%@'",predicateString,[getAllObject objectAtIndex:i],[getAllObject objectAtIndex:i+1]];
        i = i+2;
    }
    
    
    NSManagedObjectContext *context = [self managedObjectContext];
    NSEntityDescription *entity = [NSEntityDescription entityForName:self.tableName inManagedObjectContext:context];
    
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.predicate = [NSPredicate predicateWithFormat:predicateString];
    [request setIncludesPropertyValues:NO];
    [request setEntity:entity];
    NSError *error = nil;
    NSArray *datas = [context executeFetchRequest:request error:&error];
    if (!error && datas && [datas count])
    {
        for (NSManagedObject *obj in datas)
        {
            [context deleteObject:obj];
            SCDLog(@"删除成功 %@",obj);
        }
        if (![context save:&error])
        {
            SCDLog(@"删除失败 error:%@",[error localizedDescription]);
            return NO;
        }
    }
    return YES;
}
/**
 *  更新数据
 *
 *  @param mainKey   需要更新数据的主键
 *  @param mainValue 需要更新数据的主键数据
 *  @param ids       需要更新的数据的key和Value
 *
 *  @return bool
 */
- (BOOL)upDataMainKey:(NSString*)mainKey
            mainValue:(NSString*)mainValue
 andUpDataKeyAndValue:(id)ids,...NS_REQUIRES_NIL_TERMINATION;
{
    if (!self.databaseName || !self.tableName) {
        return nil;
    }
    
    NSMutableArray *getAllObject = [NSMutableArray array];
    va_list arguments;
    va_start(arguments, ids);
    NSString *getKey;
    if(ids)
    {
        while((getKey = va_arg(arguments,NSString *)))
        {
            if (getKey) {
                [getAllObject addObject:getKey];
            }
        }
    }
    va_end(arguments);
    [getAllObject insertObject:ids atIndex:0];
    NSMutableDictionary *newDic = [NSMutableDictionary dictionary];
//    [newDic setObject:[getAllObject objectAtIndex:1] forKey:[getAllObject objectAtIndex:0]];
    for (int i = 0 ;i<[getAllObject count];) {
        [newDic setObject:[getAllObject objectAtIndex:i+1] forKey:[getAllObject objectAtIndex:i]];
        i = i+2;
    }
    
    NSString *predicateString = [NSString stringWithFormat:@"%@ = '%@'",mainKey,mainValue];
    NSEntityDescription *entity = [NSEntityDescription entityForName:self.tableName inManagedObjectContext:[self managedObjectContext]];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.predicate = [NSPredicate predicateWithFormat:predicateString];
    [request setEntity:entity];
    NSError *error = nil;
    NSArray *datas = [[self managedObjectContext] executeFetchRequest:request error:&error];
    if (!error && datas && [datas count])
    {
        for(int i =0;i < [datas count];i++)
        {
            NSManagedObject *gets = [datas objectAtIndex:i];
            [self dictionaryToEntity:newDic entity:gets];
        }
    }
    if ([[self managedObjectContext] save:&error]) {
        //更新成功
        SCDLog(@"更新成功");
        return YES;
    }
    return NO;
}


- (NSUInteger)getDataCount
{
    if (!self.databaseName || !self.tableName) {
        return 0;
    }
    
    NSString *predicateString = [NSString stringWithFormat:@"COUNT(*)"];
    NSEntityDescription *entity = [NSEntityDescription entityForName:self.tableName inManagedObjectContext:[self managedObjectContext]];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.predicate = [NSPredicate predicateWithFormat:predicateString];
    [request setEntity:entity];
    NSError *error = nil;
    NSArray *datas = [[self managedObjectContext] executeFetchRequest:request error:&error];
    if (!error && datas && [datas count])
    {
        return [[datas objectAtIndex:0]integerValue];
    }
    return 0;
    
    
}
@end
